// 类型定义
export interface EncryptedData {
    salt: string;
    nonce: string;
    ciphertext: string;
    tag: string;
}

export interface DecryptionResult {
    success: boolean;
    data?: string;
    error?: string;
}

/**
 * AES-GCM 加密解密工具类
 */
export class AESCryptoUtils {
    private static readonly PBKDF2_ITERATIONS = 100000;
    private static readonly KEY_LENGTH = 256; // 256位密钥
    private static readonly TAG_LENGTH = 128; // 128位认证标签

    /**
     * 检查浏览器是否支持 Web Crypto API
     */
    public static isSupported(): boolean {
        return !!(window.crypto && window.crypto.subtle);
    }

    /**
     * Base64 字符串转 ArrayBuffer
     */
    private static base64ToArrayBuffer(base64: string): ArrayBuffer {
        try {
            const binaryString = atob(base64);
            const bytes = new Uint8Array(binaryString.length);
            for (let i = 0; i < binaryString.length; i++) {
                bytes[i] = binaryString.charCodeAt(i);
            }
            return bytes.buffer;
        } catch (error) {
            throw new Error(`Base64解码失败: ${error instanceof Error ? error.message : 'Unknown error'}`);
        }
    }

    /**
     * 使用PBKDF2派生密钥
     */
    private static async deriveKey(password: string, salt: ArrayBuffer): Promise<ArrayBuffer> {
        const keyBuffer = new TextEncoder().encode(password);

        const cryptoKey = await window.crypto.subtle.importKey(
            'raw',
            keyBuffer,
            'PBKDF2',
            false,
            ['deriveBits']
        );

        return await window.crypto.subtle.deriveBits(
            {
                name: 'PBKDF2',
                salt: salt,
                iterations: this.PBKDF2_ITERATIONS,
                hash: 'SHA-256'
            },
            cryptoKey,
            this.KEY_LENGTH
        );
    }

    /**
     * 解密字符串
     */
    public static async decryptData(
        encryptedData: string | EncryptedData,
        key: string
    ): Promise<DecryptionResult> {

        try {
            // 参数验证
            if (!encryptedData || !key) {
                return {
                    success: false,
                    error: "加密数据和密钥都不能为空"
                };
            }

            if (!this.isSupported()) {
                return {
                    success: false,
                    error: "当前浏览器不支持 Web Crypto API"
                };
            }

            // 解析加密数据
            let data: EncryptedData;
            if (typeof encryptedData === 'string') {
                try {
                    data = JSON.parse(encryptedData);
                } catch {
                    return {
                        success: false,
                        error: "无效的加密数据格式，请确保是有效的JSON"
                    };
                }
            } else {
                data = encryptedData;
            }

            // 验证数据结构
            if (!data.salt || !data.nonce || !data.ciphertext || !data.tag) {
                return {
                    success: false,
                    error: "加密数据缺少必要字段 (salt, nonce, ciphertext, tag)"
                };
            }

            // Base64解码
            const salt = this.base64ToArrayBuffer(data.salt);
            const nonce = this.base64ToArrayBuffer(data.nonce);
            const ciphertext = this.base64ToArrayBuffer(data.ciphertext);
            const tag = this.base64ToArrayBuffer(data.tag);

            // 派生密钥
            const derivedKey = await this.deriveKey(key, salt);

            // 导入AES密钥
            const aesKey = await window.crypto.subtle.importKey(
                'raw',
                derivedKey,
                'AES-GCM',
                false,
                ['decrypt']
            );

            // 合并密文和认证标签
            const encryptedBuffer = new Uint8Array(ciphertext.byteLength + tag.byteLength);
            encryptedBuffer.set(new Uint8Array(ciphertext));
            encryptedBuffer.set(new Uint8Array(tag), ciphertext.byteLength);

            // 解密
            const decryptedBuffer = await window.crypto.subtle.decrypt(
                {
                    name: 'AES-GCM',
                    iv: nonce,
                    tagLength: this.TAG_LENGTH
                },
                aesKey,
                encryptedBuffer
            );

            // 转换为字符串
            const decryptedText = new TextDecoder().decode(decryptedBuffer);

            return {
                success: true,
                data: decryptedText
            };

        } catch (error) {
            return {
                success: false,
                error: `解密失败: ${error instanceof Error ? error.message : 'Unknown error'}`,
            };
        }
    }

}